/*
 * Projet Cryptolib CPS3 ASIP:
 *
 * Couche C JNI des traitements spécifiques du programme d'exemple
 *
*/
#include "TraitementsSpecifiquesImplementation.h"
#include <stdio.h>
#include "system.h"
#include "spec_controleur.h"

/* Contexte de réalisation des appels spécifiques */
CONTEXTE_TRAITEMENTS_SPECIFIQUES_PTR g_pContexteTS = NULL;

/* 
 * Environnement JNI
 * 
 * Déclarée en variable globale pour être utilisée dans une fonction invoquée depuis la couche pure C, et ne pouvant faire référence à des types JNI
 */
JNIEnv *tmpEnv;

/* 
 * Référence de l'objet Java
 * 
 * Déclarée en variable globale pour être utilisée dans une fonction invoquée depuis la couche pure C, et ne pouvant faire référence à des types JNI
 */
jobject tmpObj;

/* Instance de la librairie PKCS#11 à utiliser */
void * librairiePKCS11 = NULL;

/* Pointeur sur la liste des fonctions de la librairie PKCS#11 */
CK_FUNCTION_LIST_PTR g_pFonctionsP11 = NULL_PTR;


/*****************/
/* Fonctions JNI */
/*****************/

/*
 * Implémentation de la méthode native qui permet de charger la librairie PKCS#11
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    connecte
 * Signature: (Ljava/lang/String;)V
 */
/* Fonction externaliser dans system.c */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_connecte
(JNIEnv *env, jobject obj, jstring js_nomLibrairie){

	CK_RV codeRetour;
	const char *nomLibrairie;
	const char nomApplication[] = "ProgrammeExemple";

	/* Conversion du nom de la librairie */
	nomLibrairie = (*env)->GetStringUTFChars(env, js_nomLibrairie, NULL);
	if (nomLibrairie == NULL) {

		log(env, obj, LOG_ERROR, cCharPtrTojstring(env, "Librairie non chargee pour cause de memoire insuffisante"));
		throwPKCS11Exception(env,CKR_HOST_MEMORY);

	}

	/* Chargement de la librairie */
	librairiePKCS11 = LoadLibrary(nomLibrairie);

	(*env)->ReleaseStringUTFChars(env, js_nomLibrairie, nomLibrairie);

	/* Si le chargement a réussi */
	if(librairiePKCS11 != NULL) {

		log(env, obj, LOG_INFO, cCharPtrTojstring(env,"Librairie chargee avec succes!"));

		/* Récupération du pointeur sur la liste des fonctions PKCS#11 */
		codeRetour = getPointeurFonctionsP11();

		/* Traitement du code retour */
		testCodeRetourOK(env, codeRetour);

		/* Initialisation du contexte des traitements spécifiques */
		g_pContexteTS = calloc(1,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));

		if(g_pContexteTS == NULL)
			throwPKCS11Exception(env,CKR_HOST_MEMORY);

		strcpy(g_pContexteTS->pNomApplication,nomApplication);

	} else
		throwPKCS11Exception(env,CKR_LIBRAIRIE_NON_CHARGEE);

}

/*
 * Implémentation de la méthode native dédiée à l'initialisation de la librairie PKCS#11
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    initialiseLibrairie
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_initialiseLibrairie
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;

	/* Si la librairie est chargée */
	if(librairiePKCS11 != NULL) {

		if(g_pFonctionsP11 != NULL) {

			/* Initialisation de la librairie */
			codeRetour = g_pFonctionsP11->C_Initialize(NULL_PTR);

			/* Si la librairie n'est pas déjà initialisée on analyse le code retour
			 * Une exception est jetée s'il est différent de CKR_OK
			 */
			if(codeRetour != CKR_CRYPTOKI_ALREADY_INITIALIZED)
				testCodeRetourOK(env, codeRetour);

		} else
			throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

	} else
		throwPKCS11Exception(env,CKR_LIBRAIRIE_NON_CHARGEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Etat de connexion à la carte
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    etatConnexionCarte
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_etatConnexionCarte
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		/* Initialisation */
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_FALSE;

		/* Invocation traitement spécifique */
		codeRetour = TS_etatConnexionCarte(g_pContexteTS);
		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Assistant authentification
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    assistantAuthentification
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_assistantAuthentification
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		// Initialisation
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_FALSE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeConnexionLecteur = demandeConnecteLecteur;
		g_pContexteTS->pDemandeInsertionCarte = demandeIntroCarte;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;

		/* Invocation traitement spécifique */
		codeRetour = TS_assistantAuthentification(g_pContexteTS);

		/* Transposition du code retour personnalisé pour le succès de l'opération d'authentification, vers le code retour standard CKR_OK */
		if(codeRetour == CKR_UTILISATEUR_AUTHENTIFIE)
			codeRetour = CKR_OK;

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Etat de saisie du code porteur
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    etatSaisieCodePorteur
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_etatSaisieCodePorteur
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		// Initialisation
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeChoixNbEssaisPossiblesAvantBlocageCodePorteur = demandeNbEssaisPossiblesAvantBlocageCodePorteur;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;

		/* Invocation traitement spécifique */
		codeRetour = TS_etatSaisieCodePorteur(g_pContexteTS);

		/* Transposition du code retour personnalisé pour le succès de l'opération d'authentification, vers le code retour standard CKR_OK */
		if(codeRetour == CKR_UTILISATEUR_AUTHENTIFIE)
			codeRetour = CKR_OK;

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
* Implémentation de la méthode native dédiée au traitement spécifique: Recyclage du code porteur
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    recyclageCodePorteur
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_recyclageCodePorteur
(JNIEnv *env, jobject obj) {


	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		// Initialisation
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_TRUE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_FALSE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeRecyclageCodePorteur = demandeRecyclage;

		/* Invocation traitement spécifique */
		codeRetour = TS_recyclageCodePorteur(g_pContexteTS);

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Assistant après retrait carte
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    authentificationApresRetraitCarte
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_authentificationApresRetraitCarte
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		// Initialisation
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_FALSE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeConnexionLecteur = demandeConnecteLecteur;
		g_pContexteTS->pDemandeInsertionCarte = demandeIntroCarte;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;
		g_pContexteTS->pDemandeActionLecteurCarte = demandeActionLecteurCarte;
		g_pContexteTS->pDeclencheAlerteCarteRetrouvee = declencheAlerteCarteRetrouvee;

		/* Invocation traitement spécifique */
		codeRetour = TS_authentificationApresRetrait(g_pContexteTS,TYPE_RETRAIT_CARTE);

		/* Transposition du code retour personnalisé pour le succès de l'opération d'authentification, vers le code retour standard CKR_OK */
		if(codeRetour == CKR_UTILISATEUR_AUTHENTIFIE)
			codeRetour = CKR_OK;

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Assistant après retrait lecteur
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    authentificationApresRetraitLecteur
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_authentificationApresRetraitLecteur
(JNIEnv *env, jobject obj) {


	CK_RV codeRetour;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		// Initialisation
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_FALSE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeConnexionLecteur = demandeConnecteLecteur;
		g_pContexteTS->pDemandeInsertionCarte = demandeIntroCarte;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;
		g_pContexteTS->pDemandeActionLecteurCarte = demandeActionLecteurCarte;
		g_pContexteTS->pDeclencheAlerteCarteRetrouvee = declencheAlerteCarteRetrouvee;

		/* Invocation traitement spécifique */
		codeRetour = TS_authentificationApresRetrait(g_pContexteTS,TYPE_RETRAIT_LECTEUR);

		/* Transposition du code retour personnalisé pour le succès de l'opération d'authentification, vers le code retour standard CKR_OK */
		if(codeRetour == CKR_UTILISATEUR_AUTHENTIFIE)
			codeRetour = CKR_OK;

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

		testCodeRetourOK(env, codeRetour);

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

}

/*
 * Implémentation de la méthode native dédiée au traitement spécifique: Lecture d'un objet de données applicatives (jeton)
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    lectureObjetDonneesApplicatives
 * Signature: ()[B
 */
JNIEXPORT jbyteArray JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_lectureObjetDonneesApplicatives
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;
	//CK_BYTE_PTR valeur = NULL_PTR;
	//CK_ULONG tailleValeur = 0;
	CK_ATTRIBUTE valeurAttributs[] = {{CKA_VALUE, NULL, 0}};
	CK_ULONG tailleValeurAttributs = sizeof(valeurAttributs)/sizeof(CK_ATTRIBUTE);
	jbyteArray jValeur = NULL;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		/* Initialisation */
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_FALSE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeConnexionLecteur = demandeConnecteLecteur;
		g_pContexteTS->pDemandeInsertionCarte = demandeIntroCarte;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;

		/* Invocation traitement spécifique */
		codeRetour = TS_lectureObjetDonneesApplicatives(g_pContexteTS, valeurAttributs, &tailleValeurAttributs);

		/* Recopie de la valeur dans tableau d'octet java */
		if(codeRetour == CKR_OK)
			jValeur = ckByteArrayToJByteArray(env, valeurAttributs[0].pValue, valeurAttributs[0].ulValueLen);

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

	/* Libération */
	if(valeurAttributs[0].pValue != NULL)
		free(valeurAttributs[0].pValue);

	testCodeRetourOK(env, codeRetour);

	return jValeur;

}

/*
* Implémentation de la méthode native dédiée au traitement spécifique: Modification d'un objet de données applicatives (jeton)
 * Class:     fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation
 * Method:    modificationObjetDonneesApplicatives
 * Signature: ()[B
 */
JNIEXPORT jbyteArray JNICALL Java_fr_asip_cps3_exemple_modele_jni_TraitementsSpecifiquesImplementation_modificationObjetDonneesApplicatives
(JNIEnv *env, jobject obj) {

	CK_RV codeRetour;
	//CK_BYTE_PTR valeur = NULL_PTR;
	//CK_ULONG tailleValeur = 0;
	CK_ATTRIBUTE valeurAttributs[] = {{CKA_VALUE, NULL, 0}};
	CK_ULONG tailleValeurAttributs = sizeof(valeurAttributs)/sizeof(CK_ATTRIBUTE);
	jbyteArray jValeur = NULL;

	/* Si la liste des fonctions n'est pas nulle */
	if(g_pFonctionsP11 != NULL) {

		// On initialise les variables JNI globales
		// Pour permettre l'appel sous forme de callback aux fonctions développées au niveau Java
		tmpEnv = env;
		tmpObj = obj;

		/* Initialisation */
		memset(g_pContexteTS,0,sizeof(CONTEXTE_TRAITEMENTS_SPECIFIQUES));
		g_pContexteTS->pFonctionsP11 = g_pFonctionsP11;
		g_pContexteTS->estSessionLectureEcriture = CK_TRUE;
		g_pContexteTS->verifierConformiteCodeAvantAuthentification = CK_TRUE;
		g_pContexteTS->mentionnerNbEssaisRestantsAvantAuthentification = CK_TRUE;
		g_pContexteTS->pDemandeConnexionLecteur = demandeConnecteLecteur;
		g_pContexteTS->pDemandeInsertionCarte = demandeIntroCarte;
		g_pContexteTS->pDemandeSaisieCodePorteur = demandeCodePorteur;
		g_pContexteTS->pDemandeModificationObjet = demandeModificationObjet;

		/* Invocation traitement spécifique */
		codeRetour = TS_modificationObjetDonneesApplicatives(g_pContexteTS, valeurAttributs, &tailleValeurAttributs);

		/* Recopie de la valeur dans tableau d'octet java */
		if(codeRetour == CKR_OK)
			jValeur = ckByteArrayToJByteArray(env, valeurAttributs[0].pValue, valeurAttributs[0].ulValueLen);

		// On remet à 0 les variables JNI globales
		tmpEnv = NULL;
		tmpObj = NULL;

	} else
		throwPKCS11Exception(env,CKR_LISTE_FONCTIONS_NON_INITIALISEE);

	/* Libération mémoire */
	if (valeurAttributs[0].pValue != NULL)
		free(valeurAttributs[0].pValue);

	testCodeRetourOK(env, codeRetour);

	return jValeur;

}




/*************************/
/* Fonctions utilitaires */
/*************************/



/*
 * Demande de connexion d'un lecteur
 *
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Relancer)
 */
int demandeConnecteLecteur() {
	
	return (int) demandeConnexionLecteur(tmpEnv,tmpObj);

}

/*
 * Demande d'insertion d'une carte supportée
 *
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Relancer)
 */
int demandeIntroCarte() {
	
	return (int) demandeInsertionCarte(tmpEnv,tmpObj);

}

/* 
 * Demande du choix du nombre d'essais possibles avant blocage du code porteur
 *
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour N Tentative/ 2 pour 3 Tentatives)
 */
int demandeNbEssaisPossiblesAvantBlocageCodePorteur() {
	
	return demandeChoixNbEssaisPossiblesAvantBlocageCodePorteur(tmpEnv,tmpObj);

}

/* 
 * Demande de saisie du code porteur
 *
 * @param nbEssais - Flag permettant de déterminer le message à afficher concernant le nombre d'essai
 * @param conformiteCodePorteur - Etat de conformité du code porteur
 * @param code - Le code porteur erroné
 * @param numeroSerieCarte - numéro de série de la carte
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Valider)
 */
int demandeCodePorteur(CK_FLAGS nbEssais, CK_FLAGS conformiteCodePorteur, char** code, unsigned char numeroSerieCarte[16]) {
	
	return demandeSaisieCodePorteur(tmpEnv, tmpObj, nbEssais, conformiteCodePorteur, code, numeroSerieCarte);

}

/* 
 * Demande de recyclage du code porteur
 *
 * @param nbEssais - flag permettant de déterminer le message à afficher concernant le nombre d'essai
 * @param conformiteCodeDeblocage - état de conformité du code de déblocage
 * @param conformiteCodePorteur - état de conformité du code porteur
 * @param codeDeblocage - code de déblocage saisi
 * @param nouveauCodePorteur1 - 1er nouveau code porteur saisi
 * @param nouveauCodePorteur2 - 2eme nouveau code porteur saisi
 * @param numeroSerieCarte - numéro de série de la carte
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Valider)
 */
int demandeRecyclage(CK_FLAGS nbEssais, CK_FLAGS conformiteCodeDeblocage, CK_FLAGS conformiteCodePorteur, char** codeDeblocage, char** nouveauCodePorteur1, char** nouveauCodePorteur2, unsigned char numeroSerieCarte[16]) {
	
	return demandeRecyclageCodePorteur(tmpEnv,tmpObj,nbEssais,conformiteCodeDeblocage,conformiteCodePorteur,codeDeblocage,nouveauCodePorteur1,nouveauCodePorteur2, numeroSerieCarte);

}

/* 
 * Demande d'action lecteur (retrait/connexion) ou carte (retrait/insertion)
 *
 * @param typeActionAttendue - type d'action à demander
 * @param numeroSerieCarte - numéro de série de la carte
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Valider)
 */
int demandeActionLecteurCarte(int typeActionAttendue, unsigned char numeroSerieCarte[16]) {
	
	return demandeActionSurLecteurCarte(tmpEnv,tmpObj,typeActionAttendue,numeroSerieCarte);

}

/*
 * Alerte de carte retrouvée
 *
 */
void declencheAlerteCarteRetrouvee() {
	
	alerteCarteRetrouvee(tmpEnv,tmpObj);

}

/* 
 * Demande de saisie de modification d'un objet
 *
 * @param valeur - La valeur de l'attribut de l'objet
 * @param tailleValeur - Taille de la valeur de l'attribut de l'objet
 * @param pValeurModifiee - Référence sur la valeur modifiée de l'attribut de l'objet
 * @param tailleValeurModifiee - Taille de la valeur modifiée de l'attribut de l'objet
 * @return Le choix utilisateur (-1 pour Annulation / 1 pour Valider)
 */
int demandeModificationObjet(CK_BYTE_PTR valeur, CK_ULONG tailleValeur, CK_BYTE_PTR *pValeurModifiee, CK_ULONG_PTR tailleValeurModifiee) {
	
	return demandeSaisieModificationObjet(tmpEnv, tmpObj, valeur, tailleValeur, pValeurModifiee, tailleValeurModifiee);

}

/*
 * Récupération du pointeur sur la liste des fonctions de la librairie PKCS#11
 *
 * @return Code retour
 */
CK_RV getPointeurFonctionsP11() {

	/* Adresse de la fonction C_GetFunctionList de la librairie PKCS#11 chargée */
	CK_C_GetFunctionList pC_GetFunctionList;

	/* Si la librairie est chargée */
	if(librairiePKCS11 != NULL) {

		/* Retourne l'adresse de la fonction C_GetFunctionList de la librairie PKCS#11 chargée */
		pC_GetFunctionList = (CK_C_GetFunctionList)GetProcAddress(librairiePKCS11,(const char*)"C_GetFunctionList");
		if ( pC_GetFunctionList == NULL) {
			return CKR_LISTE_FONCTIONS_INDISPONIBLE;
		}

		/* Retourne ce que renvoie la fonction */
		return (*pC_GetFunctionList)(&g_pFonctionsP11);

	} else
		return CKR_LIBRAIRIE_NON_CHARGEE;

}
